import { coordinate, plainMatrix, _random } from "../math/index.js"
import { gridCrossPoints } from "../algorithm/grid.js"
import { treeLine } from "./path.js"
import { _labels } from "./polygon.js"
import { renderShape } from "./renderShape.js"
import { _g } from "./svg.js"

// 初始化状态
const initMazeStatus = (coors) => {
    let m = coors.length - 1
    let n = coors[0].length - 1

    return coors.map(row => {
        return row.map(t => {
            let [x, y] = t
            let up = 1, right = 1, bottom = 1, left = 1
            if (x === 0) {
                left = 0
            }
            if (x === n) {
                right = 0
            }
            if (y === 0) {
                up = 0
            }
            if (y === m) {
                bottom = 0
            }
            return [up, right, bottom, left]
        })
    })
}
// 当前状态
const getCurrentStatus = (mazeStatus = [], current = []) => {
    let [x, y] = current
    let currentStatus = mazeStatus[y][x]
    return currentStatus
}

// 可移动方向
// 用0123表示 方向[up, right, bottom, left]
// const getCanMoveDirect = (currentStatus) => {
//     return currentStatus.map((t, i) => {
//         return {
//             index: i,
//             status: t
//         }
//     }).filter(t => t.status).map(t => t.index)
// }



// 用0123表示 方向[up, right, bottom, left]
const getNext = (current, direct) => {
    let [x, y] = current
    switch (direct) {
        case 0:
            y -= 1
            break;
        case 1:
            x += 1
            break;
        case 2:
            y += 1
            break;
        case 3:
            x -= 1
            break
    }
    return [x, y]
}

// 反方向 进口方向
// [0,1,2,3]
// [2,3,0,1]
const inDirect = (direct) => {
    return [2, 3, 0, 1][[0, 1, 2, 3].indexOf(direct)]
}
// 邻居
const getNeighbours = (current, n, m) => {
    return [0, 1, 2, 3].map(t => {
        // return getNext(current, t)
        return {
            direct: t,
            pos: getNext(current, t)
        }
    }).filter(t => {
        let [x, y] = t.pos
        return x >= 0 && y >= 0 && x < n && y < m
    })
}

const getCanMove = ({ pos, status }) => {
    return status.map((t, i) => {
        return {
            status: t,
            direct: i,
            pos: t ? getNext(pos, i) : null,
        }
    }).filter(t => t.status)
}
// 用0123表示 方向[up, right, bottom, left]
const _setStatus = (mazeStatus, current, direct) => {

    let [x, y] = current
    if (x < 0 || y < 0) return mazeStatus
    // mazeStatus[y][x] =[0,0,0,0]
    if (!mazeStatus[y]) return mazeStatus
    let currentStatus = mazeStatus[y][x]
    if (!currentStatus) return mazeStatus
    mazeStatus[y][x] = currentStatus.map((t, i) => {
        return direct === i ? 0 : t
    })
    return mazeStatus
}


// 移动
const move = (mazeStatus = [], current = [], his = [[]], stack = []) => {
    if (!current) return
    let m = mazeStatus.length
    let n = mazeStatus[0].length

    let currentStatus = getCurrentStatus(mazeStatus, current)
    // 可移动方向和坐标
    let canMove = getCanMove({
        pos: current,
        status: currentStatus
    })

    his[his.length - 1].push(current)
    stack.push(current)

    // 当前节点不能进了
    let neighbours = getNeighbours(current, n, m)
    neighbours.forEach((t) => {
        _setStatus(mazeStatus, t.pos, inDirect(t.direct))
    })

    if (canMove.length > 0) {
        // 随机选择
        let next = _random(canMove)
        // 当前节点出路去了一条
        _setStatus(mazeStatus, current, next.direct)
        move(mazeStatus, next.pos, his, stack)
    } else {
        // 退回重新走
        if (stack.length === 2) {
            if (his[his.length - 1].length === 1) {
                his.pop()
            }
            return
        }
        stack.pop()
        // 上一个
        let next2 = stack.pop()
        if (!next2) return
        if (Array.isArray(next2)) {
            // new branch
            let len = his[his.length - 1].length
            if (len === 0) return
            if (len === 1) {
                his[his.length - 1] = []
            }
            else if (len > 1) {
                his.push([])
            }
            move(mazeStatus, next2, his, stack)
        }
    }
}
// 迷宫
export const _maze = (options, props) => {
    let { height = 600,
        width = 800,
        o = [400, 300],
        r = 50,
        padding = 30,
        start = [0, 0],
        vertex = {},
        label
    } = options
    let gps = gridCrossPoints({
        height,
        width,
        o,
        r,
        padding
    })

    let coors = coordinate(gps)
    let mazeStatus = initMazeStatus(coors)
    let his = [[]]
    let stack = []
    move(mazeStatus, start, his, stack)

    let pointTree = his.map(row => {
        return row.map(t => {
            let [x, y] = t
            return gps[y][x]
        })
    })

    let line = treeLine(pointTree, {
        id: 'maze_path',
        stroke: 'red',
        strokeWidth: 2,
        fill: 'none'
    })

    let children = [line]

    let mps = plainMatrix(his).map(t => {
        let [x, y] = t
        return gps[y][x]
    }) //.slice(0, 30)



    if (vertex) {
        let nodes = mps.map((t, i) => renderShape({
            shape: 'circle',
            o: t,
            r: 5,
            // motion: {
            //     id: (i === 0) ? 'maze_path' : '',
            //     dur:'60s'
            // },
            ...vertex
        }, {
            fill: (i === 0) ? 'red' : 'rgba(0,0,0,0.5)',
            stroke: 'none',
            ...vertex.props
        }))

        children.push(nodes)
    }

    if (label) {
        let labels = _labels({
            points: mps
        }, label, props)
        children.push(labels)
    }

    return _g(children)
}